iT邦幫忙

2022 iThome 鐵人賽

DAY 16
1
AI & Data

機器學習的 hello world - 用手寫數字辨識系統學習 ML 的 30 天系列 第 16

[DAY16] 使用 Keras 實作手寫數字辨識系統-含程式碼

  • 分享至 

  • xImage
  •  

今天我們將完整拼疊出一個手寫數字辨識系統,這邊會以

  • 模型的建立與訓練
    • 前處理-資料轉換
      • 圖片(模型輸入)
      • 標籤(模型輸出)
    • NN model 的建立與訓練
      • 找一個 model / 建立一個 NN structure
      • 定義 model 的好壞並選最好的
  • 待預測的輸入圖形式
  • 模型預測

三個部分來說明,這一篇的完整程式碼可以看這 → DAY16-MNIST-MLP


一、模型的建立與訓練

(1) 前處理-資料轉換

模型建立訓練前一定有資料。在資料的部分,我們使用的是 MNIST 資料集,並會對其做一些資料格式的轉換,讓它符合模型輸入輸出需要的形式

ps. MNIST 資料集的介紹可以看 DAY15 使用 Keras 拼出手寫數字辨識系統的前置作業2-MNIST 資料集

1.圖片(模型輸入)

首先我們會先將資料集的圖片從二維(28*28)轉成一維(784),因為這樣才能與神經網路的輸入層結構匹配。這邊我們借用 Numpy 的 reshape()astype() 功能,將原本 0~255 的 uint8 整數像素資料型態轉成 float32 浮點數,因為在處理圖片做圖片或資料計算時通常都是用浮點數運算。

再來我們會做資料正規化,將所有的數值正規化到 0~1 之間,因為這樣模型的訓練成效會更好,而最簡單的正規化就是除以最大值。

# convert 28x28 image to 784 array, datatype unit8 -> float32
x_train = train_image.reshape(60000, 784).astype('float32') #np.float32
x_test = test_image.reshape(10000, 784).astype('float32')

# normalize the image numbers to 0~1
x_train /= 255   # x_train = x_train / 255           
x_test /= 255

2.標籤(模型輸出)

標籤的部分可以不做前處理(不轉換成 one hot 形式),但模型架構 loss function 的部分記得要設定成 loss=’sparse_cross_entropy'。而我們這邊因為使用 loss=’cross_entropy’,所以將模型輸出要比對的資料形式改成 one-hot 編碼。

# convert label numbers to one-hot encoding
from tensorflow.keras.utils import to_categorical

y_train=to_categorical(train_label, 10)     
y_test=to_categorical(test_label, 10)

https://ithelp.ithome.com.tw/upload/images/20220930/201317190fHdS9Vbt7.png


(2) NN model 的建立與訓練

這邊使用神經網路找方法三步驟來說明~

1. 找一個 model / 建立一個 NN structure

# import 建 model 需要的套件
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras import optimizers

# 定義此 model 模式為 sequential model
model = Sequential()
model.add(Dense(units=64, input_dim=784, kernel_initializer='normal', activation='relu')) #輸入+隱藏層
model.add(Dense(units=10, kernel_initializer='normal', activation='softmax')) #輸出層
print(model.summary())

https://ithelp.ithome.com.tw/upload/images/20220930/20131719W9EBQxCMKN.png

後面會再提到什麼是 MLP(multilayer neural network/multilayer perceptron)與Dense意義,這邊先知道神經網路模型會分成輸入層、中間的隱藏層跟最後的輸出層就好。我們看model,這邊 model 呼叫了兩次 add(),但實際上是建立了三層模型,一層輸入層、一層隱藏層跟一層輸出層,因為第一次呼叫的 add 同時建立了輸入層(input_dim=784維)跟隱藏層(units=64個神經元,unit可不寫)。第二次呼叫 add()時不需要指定 input_dim,因為上一層的輸出就是這一層的輸入(64個神經元)。這邊每層的一開始我有初始化權重(kernel_initializer),而 activation 的選擇可看 [DAY8] 讓 NN model 引入非線性-激勵函數(activation function)

在模型建立這邊有一個容易被問到的問題是,怎麼設定每層的 neuron 個數呢?這個目前沒有標準答案(我是看結果去試64/128/256等二的倍數哈)。不過這邊有討論大家可以參考一下 → 如何決定 NN中 hidden layer 數以及每層的 neurons?

2. 定義 model 的好壞並選最好的

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
train_history =model.fit(x=x_train, y=y_train, epochs=20, batch_size=64, validation_split=0.2)

關於編譯(compile) model 裡的參數,可以看:
[DAY9] 評估 NN model 好壞的指標-損失函數(loss function)
[DAY10] NN model 學習的核心-優化器(optimizer)
[DAY12] 評估結果成效的準則-性能指標(metrics)

而訓練(fit)的部分,傳入訓練集圖片(x_train)及標籤(y_train),epochbatch_sizevalidation_split 可以看:
[DAY11] NN model 的訓練設定-訓練週期(epoch) 與 批次(batch)
[DAY13] 資料的劃分-訓練集(training set)、驗證集(validation set) 與 測試集(testing set)

這邊我使用 train_history 這個變數把過程存下來,以便可以比較視覺化的繪圖看結果。

https://ithelp.ithome.com.tw/upload/images/20221001/201317192U67t737WA.png

ps.如果想要 Save and load Keras models 所有變數與訓練結果,可以用模型 .h5 檔或 .pb 檔存下來,詳見tensorflow官網


二、待預測的輸入圖形式

在預測的輸入圖這邊,我使用的是與 DAY4 使用 OCR 來快速實做出手寫數字辨識系統 相同的三張圖,以符合我們實作手寫數字辨識系統的需求。這三張圖片分別是:

  • number_print:在word上打字截圖(字型Calibri)
  • number_paint:使用小畫家手寫圖片
  • number_handwritten:寫在紙上拍照的圖片

三張圖片均有簡單裁切並調正但大小不一。
https://ithelp.ithome.com.tw/upload/images/20220930/201317190fuydxxUe0.png


三、模型預測

import os
os.chdir('/content/drive/MyDrive/Colab Notebooks')  # Colab 換路徑使用

from PIL import Image
img = Image.open('number_paint.png').convert('L') #灰階圖片
img = img.resize((28,28))

# 轉換格式
im = np.array(img).astype('float32') 
im = (255-im)/255
im = im.reshape(784,1)
im = np.expand_dims(im, 0)

# 預測
np.argmax(model.predict(im))

三張圖片只有 number_print 跟number_paint 辨識成功,number_handwritten 可能是因為前處理不夠而無法辨識出。那麼問題來了,要怎麼修改模型或做前處理讓這個手寫辨識系統變的更符合預期呢?以及要怎麼解釋訓練過程中的loss跟accuracy?明天我們會來說明預測結果,跟怎麼根據結果調整我們的程式碼~


上一篇
[DAY15] 使用 Keras 拼出手寫數字辨識系統的前置作業2-MNIST 資料集
下一篇
[DAY17] 實作結果與調整方向-概念介紹(error/bias/variance)
系列文
機器學習的 hello world - 用手寫數字辨識系統學習 ML 的 30 天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Jas020522
iT邦新手 5 級 ‧ 2023-03-22 21:01:28

嗨~不好意思,我想請問一下,# Colab 換路徑使用,是什麼意思呢?謝謝!

sysherry iT邦新手 4 級 ‧ 2023-09-14 22:43:27 檢舉

不好意思現在才看到@@ 因為os.chdir(path)這個指令是改變路徑到我想要的資料夾位置,所以才會在後面註解 # Colab 換路徑使用,可以不加,或檔案在不同位置時進行相對應的修改

我要留言

立即登入留言